
#ifndef DBPARITIONIMPL_H_
#define DBPARITIONIMPL_H_

#include "status.hxx"
#include "db/compact.hxx"
#include "util/ratelimiting.hxx"


class DbEnvImpl;


struct CompactOption {

public:
    bool m_enabled;
    bool m_quit;
    double m_validDataRatio;

    //throttling
    RateLimiting m_throttling;

    //the number of segments which should be compacted
    uint32_t m_segs;
    bool m_compacting;

    //return true if want to quit compact;
    bool shouldDone() {
        return m_enabled == false || m_quit == true;
    }

};


class CompactImpl : public Compact {

private:
    CompactOption m_option;
    uint32_t m_interval;

    pthread_mutex_t m_mutex;
    pthread_cond_t m_cond;
    DbEnvImpl * m_env;

    //indicate whether compact thread already quit
    bool m_alreadyQuit;

    static Compact* m_instance;

public:
    CompactImpl(DbEnvImpl& env);
    ~CompactImpl();

    DbStatus init();

    void start();
    void stop(bool quit);

    void enableThrottling();
    void disableThrottling();
    bool isEnabled();

    void setThrottling(uint32_t M, uint32_t N);
    void setValidDataRatio(double ratio);
    double getValidDataRatio();

    void notify();
    uint64_t timeToWait();

    static Compact* getInstance();
    static Compact* getInstance(DbEnvImpl& env);

private:
    static void * compactThreadFunc(void* arg);

};


struct CompactIndexItem {

public:
    CompactIndexItem(uint32_t index, uint64_t addr);
    uint32_t m_index;
    uint64_t m_addr;
};


class CompactIndexCompartor {

public:
    CompactIndexCompartor() {}
    bool operator()(const CompactIndexItem& left, const CompactIndexItem& right);
};

#endif
